package ProxyTester;

##########################
#     OmnibusProxy       #
#    Krzysztof Ulman     #
# Politechnika Krakowska #
#      Kraków 2012       #
##########################

use strict;
use warnings;

use LWP::Simple;
use Try::Tiny;
use WWW::Mechanize;

use AppConfig;
use ProxyDto;
use Screen;

#statusy proxy
our $STATE_OK = 'OK';
our $STATE_ERROR = 'ERROR';
our $HIDES_YES = 'YES';
our $HIDES_NO = 'NO';

#standardowy IP, bez uzycia proxy 
our $orginalIp;

#adres do sprawdzenia ip
our $WHAT_IS_MY_IP_URL;

#czas oczekiwania na odpowiedz
our $WHAT_IS_MY_IP_TIMEOUT;

#czas pomiedzy poszczegolnymi sprawdzeniami
our $SLEEP_TIME;

#czas ostatniego sprawdzania IP
our $lastCheckTime;

#konstruktor
sub new {
	shift;
	my $self = {};
	bless $self;
	
	$WHAT_IS_MY_IP_URL = AppConfig->getProperty('WHAT_IS_MY_IP_URL'); 
	$SLEEP_TIME = AppConfig->getProperty('WHAT_IS_MY_IP_SLEEP_TIME');
	$WHAT_IS_MY_IP_TIMEOUT = AppConfig->getProperty('WHAT_IS_MY_IP_TIMEOUT');
	
	private_getOrginalIp();
	
	return $self;	
}

#rozpoczyna testowanie podanego proxy
sub testProxy {
	my $self = shift;
	my $proxyDto = shift;
	
	my $diffTime = time - $lastCheckTime;
	if($diffTime < $SLEEP_TIME) {
		sleep($SLEEP_TIME - $diffTime);
	}
	
	my $result = private_doTest($proxyDto);
	$lastCheckTime = time;
	
	return $result;
}

#testuje czy za pomoca proxy podlaczymy sie do wyszukiwarki
sub testProxyWithSearcher {
	my $self = shift;
	my $proxyDto = shift;
	my $searcherDto = shift;
	
	my $diffTime = time - $lastCheckTime;
	if($diffTime < $SLEEP_TIME) {
		sleep($SLEEP_TIME - $diffTime);
	}
	
	my $state = private_doTestWithSearcher($proxyDto, $searcherDto->getUrl(), $searcherDto->getName());
	$lastCheckTime = time;
	
	return $state;
}

#pobiera oryginalny adres IP komputera
sub private_getOrginalIp {
	if(!$orginalIp) {
		try {
			my $ip = get($WHAT_IS_MY_IP_URL); #'http://automation.whatismyip.com/n09230945.asp' OPIS: http://www.whatismyip.com/faq/automation.asp
			chomp $ip;
			$lastCheckTime = time;
			if($ip && $ip =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
				$orginalIp = $ip;
				Screen->printAndLogInfo('Orginal IP is ' . $orginalIp);
			} else {
				die('No own IP found');
			}
		} catch {
			$orginalIp = '0.0.0.0'; #default, jezeli nie udalo sie pobrac
			my $e = $_;
			Screen->printAndLogError($e);
		};
	}
}

#testuje pojedyncze proxy
sub private_doTest {
	my $proxyDto = shift;
	
	my $browser = WWW::Mechanize->new();
	try {
		my $proxyAddr = $proxyDto->getAddress();
		if(!($proxyAddr =~ /^http\:\/\//)) {
			$proxyAddr = 'http://' . $proxyAddr;
		}
		$proxyAddr .= ':' . $proxyDto->getPort();
		$browser->proxy('http', $proxyAddr);
		$browser->timeout($WHAT_IS_MY_IP_TIMEOUT);
		
		$browser->get($WHAT_IS_MY_IP_URL);
		if($browser->success()) {
			my $ip = $browser->content();	
			if($ip 
				&& $ip =~ /^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/) {
					$proxyDto->setState($STATE_OK);
					Screen->printAndLogDebug('Proxy OK: ' . $proxyAddr);
					if($ip ne $orginalIp) {
						$proxyDto->setHidesRealIp($HIDES_YES);
					} else {
						$proxyDto->setHidesRealIp($HIDES_NO);
					}
			} else {
				die('No IP found');
			}		
		} else {
			die($proxyAddr . ' - ' . $browser->response()->status_line());
		}
		
	} catch {
		$proxyDto->setState($STATE_ERROR);
		my $e = $_;
		Screen->printAndLogError($e);
	};
}

#testuje polaczenie do wskazanej wyszukiwarki przez wskazane proxy
sub private_doTestWithSearcher {
	my $proxyDto = shift;
	my $url = shift;
	my $searcherName = shift;
	my $state;
	
	my $browser = WWW::Mechanize->new();
	try {
		my $proxyAddr = $proxyDto->getAddress();
		if(!($proxyAddr =~ /^http\:\/\//)) {
			$proxyAddr = 'http://' . $proxyAddr;
		}
		$proxyAddr .= ':' . $proxyDto->getPort();
		$browser->proxy('http', $proxyAddr);
		$browser->timeout($WHAT_IS_MY_IP_TIMEOUT);
		
		$browser->get($url);
		if($browser->success()) {
			my $content = $browser->content();
			if($content =~ /$searcherName/i) {
				$state = $STATE_OK;
			} else {
				$state = $STATE_ERROR;
			}
		} else {
			die($proxyAddr . ' - ' . $url . ' - ' . $browser->response()->status_line());
		}
		
	} catch {
		$state = $STATE_ERROR;
		my $e = $_;
		Screen->printAndLogError($e);
	};
	
	return $state;
}

1;